using System;
using System.Collections.Generic;
using System.Text;
using Barrage;
using Barrage.Global;
using SlimDX;
using SlimDX.Direct3D9;
using Barrage.Global.Vertex;

namespace Barrage.GUI.Meshes
{
    /// <summary>
    /// Represents a rectangle that can be rendered on 2D Scenes
    /// </summary>
    public class SimpleRectangle : Barrage.Meshes.GuiMesh
    {
        private bool dirty = false;
        private Vector2 size;

        /// <summary>
        /// The rectangle size in pixels
        /// </summary>
        public Vector2 Size { get { return size; } set { size = value; dirty = true; } }

        private Vector2 offset;

        /// <summary>
        /// Rectangle's geometry center offset (normally it'll be a zero vector)
        /// </summary>
        public Vector2 Offset { get { return offset; } set { offset = value; dirty = true; } }


        private VertexBuffer rectangleBuffer = null;

        private void initializeBuffer()
        {
            rectangleBuffer = new VertexBuffer(Engine.Device, VertexPositionUV.SizeBytes * 4, Usage.WriteOnly, VertexPositionUV.Format, Pool.Managed);
            fillBuffer();
        }

        private void fillBuffer()
        {
            DataStream stream = rectangleBuffer.Lock(0, 0, LockFlags.None);
            VertexPositionUV[] vertices = generateVertices();
            stream.WriteRange(vertices);
            rectangleBuffer.Unlock();

            dirty = false;

        }

        private VertexPositionUV[] generateVertices()
        {
            VertexPositionUV[] vertices = new VertexPositionUV[4];
            Vector2 halfSize = size / 2.0f;
            vertices[0].Position = new Vector3(-halfSize.X + offset.X, halfSize.Y + offset.Y, 0); vertices[0].UV = new Vector2(0, 0);
            vertices[1].Position = new Vector3(halfSize.X + offset.X, halfSize.Y + offset.Y, 0); vertices[1].UV = new Vector2(1, 0);
            vertices[2].Position = new Vector3(-halfSize.X + offset.X, -halfSize.Y + offset.Y, 0); vertices[2].UV = new Vector2(0, 1);
            vertices[3].Position = new Vector3(halfSize.X + offset.X, -halfSize.Y + offset.Y, 0); vertices[3].UV = new Vector2(1, 1);
            
            return vertices;

        }

        /// <summary>
        /// Initializes the geometry and materials
        /// </summary>
        /// <param name="texture">Texture that the rectangle will use</param>
        /// <param name="size">Initial size in pixels</param>
        public SimpleRectangle(Texture texture, Vector2 size)
        {
            this.size = size;
            initializeBuffer();
            Materials[0].Texture = texture;

        }


        /// <summary>
        /// \internal Renders the rectangle
        /// </summary>
        /// <param name="item">Item that is being rendered</param>
        public override void Render(Item item)
        {
            RenderStats.RenderCalls++;
            shader.BeginRender(item, materials[0]);
            if (dirty) { fillBuffer(); }
            Engine.Device.VertexFormat = VertexPositionUV.Format;
            Engine.Device.SetStreamSource(0, rectangleBuffer, 0, VertexPositionUV.SizeBytes);
            int passNumber = shader.PassNumber(materials[0]);
            for (int j = 0; j < passNumber; j++)
            {
                shader.BeginPass(j);
                Engine.Device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
                shader.EndPass();
            }
            shader.EndRender();

        }

        /// <summary>
        /// \internal Free resources
        /// </summary>
        public override void Dispose(){
            rectangleBuffer.Dispose();
            rectangleBuffer = null;
            base.Dispose();
        }
    }
}
